<?php
namespace Core;

use Core\DzInternetProtocol;
use Core\Model;

class CommandProtocol
{
    private $protocol;
    private $db;
    public $upconfig;
    public function __construct()
    {
        $this->protocol=new DzInternetProtocol();
        $this->db=Model::init('confcommander');
        $this->upconfig = require_once ROOT . '/config/upgrade.config.php';
    }

    public function setcommand($cmd,$data,$token)
    {
        if(!method_exists($this,$cmd))
            return array('code'=>0,'errotext'=>'命令无效','data'=>$cmd);

       // dump('in_cmd');
        //dump($token, $cmd);
        $returnresult=$this->$cmd($token,$data);
       // dump($cmd, $returnresult);
        if(isset($returnresult['code']) || is_array($returnresult) || false===$returnresult || '0'===$returnresult || empty($returnresult))
            return array('code'=>-1,'errotext'=>'命令无效','data'=>$returnresult);
        else
            return bin2hex($returnresult);
    }

    /**
     * 连接请求响应
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:44
     */
    public function getconnect($token=0,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'00','sdt'=>'0100']);
    }

    /**
     * 发送token
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:45
     */
    public function sendtoken($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'1000'],['do'=>'sdtoken'],$token);
    }

    /**
     * 发送心跳
     * @param $token
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:46
     */
    public function sentheart($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'1000'],['do'=>'heart'],$token);
    }

    /**
     * 设置心跳间隔
     * @param int $timer
     * @param $token
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:21
     */
    public function setheart($token,$data=[])
    {
        $timer=$data['data']?:1;
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'1000'],['do'=>'setheart','data'=>$timer],$token);

    }

    /**
     * 获取心跳间隔
     * @param $token
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:57
     */
    public function getheart($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'1000'],['do'=>'getheart'],$token);
    }


    /**
     * 能力获取
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:53
     */
    public function getability($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0000'],['do'=>'getability'],$token);
    }

    /**
     * 获取设备信息
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:47
     */
    public function getdeviceinfo($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0110'],['do'=>'getdeviceinfo'],$token);
    }

    /**
     * 获取设备状态信息
     * @param $token
     * @param array $data
     * @return array|bool|string
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/5 9:16
     */
    public function getdevicestatus($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0110'],['do'=>'getdevicestatus'],$token);
    }

    /**
     * 获取位置信息
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:52
     */
    public function getdeviceloc($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0110'],['do'=>'getdeviceloc'],$token);
    }


    /**
     * 获取位置基站信息
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:52
     */
    public function getlbslocbase($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0110'],['do'=>'getlbslocbase'],$token);
    }


    /**
     * 获取位置SIM卡信息
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:52
     */
    public function getsmbaseinfo($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0110'],['do'=>'getsmbaseinfo'],$token);
    }

    /**
     * 获取故障信息
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:54
     */
    public function geterro($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0101'],['do'=>'geterro'],$token);
    }

    /**
     * 设置工作布控模式
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:48
     */
    public function setworkmode($token,$data=[])
    {
        if(!isset($data['data'])) return false;
        if(!in_array((int)$data['data'],[1,2,3,4])) return false;
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setworkmode','data'=>$data['data']],$token);
    }

    /**
     * 设置过滤策略 -和布控模式联合使用
     * @param $type
     * @param $macs
     * @param $token
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:50
     */
    public function setfiltermode($token,$data=[])
    {
        if(!isset($data['type'])|| !isset($data['macs'])) return false;
        if(!in_array((int)$data['type'],[1,2,3])) return false;
        $type=$data['type'];
        $macs=$data['macs'];
        if($type=='3'){
           if((strlen($macs)%8) >0) return false;
        }else{
            if((strlen($macs)%6) >0) return false;
        }
//        $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setfiltermode','type'=>1,'macs'=>'ffffffffffff120000000044'],$token);
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setfiltermode','type'=>$type,'macs'=>$macs],$token);
    }

    /**
     * 获取过滤策略
     * @param $token
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 9:51
     */
    public function getfiltermode($token,$data=[])
    {
        if(!isset($data['type'])) return false;
        if(!in_array((int)$data['type'],[1,2,3])) return false;
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'getfiltermode','data'=>$data['type']],$token);
    }

    /**
     * 获取数据上报间隔
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:02
     */
    public function getdatatimer($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'getdatatimer'],$token);
    }

    /**
     *  设置数据上报间隔
     * @param $data ['sta'=>1,'ap'=>1,'rf'=>1]
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:05
     */
    public function setdatatimer($token,$data=[])
    {
        if(empty($data)) return false;

        $option=['do'=>'setdatatimer'];
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],array_merge($option,$data),$token);
//        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setdatatimer','sta'=>1],$token);
    }

    /**
     * 获取数据上报方式
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:07
     */
    public function getdatauptype($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'getdatauptype'],$token);
    }

    /**
     * 设置数据上报方式
     * @param $type
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:07
     */
    public function setdatauptype($token,$data=[])
    {
        if(!isset($data['data'])) return false;
        if(!in_array((int)$data['data'],[1,2])) return false;
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setdatauptype','data'=>$data['data']],$token);
    }

    /**
     * 设置域名和端口
     * @param $cfgsv
     * @param $datasv
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:09
     */
    public function setdnsport($token,$data=[])
    {
        if(!isset($data['cfgsv'])|| !isset($data['datasv'])) return false;
        $cfghost=explode(":",$data['cfgsv'])[0];
        $dthost=explode(":",$data['datasv'])[0];

        if(strlen($cfghost)>=64 || strlen($dthost)>=64)
            return array('code'=>1,'errotext'=>'域名长度超出范围');

        if(!preg_match('/^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$/i', $cfghost))
            return array('code'=>2,'errotext'=>'控制服务器域名非法,域名中不包括：:// 等非法字符');

        if(!preg_match('/^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$/i', $dthost))
            return array('code'=>2,'errotext'=>'数据服务器域名非法,域名中不包括：:// 等非法字符');

        if((int)explode(":",$data['cfgsv'])[1]>65535)
            return array('code'=>3,'errotext'=>'数据服务器端口非法');

        if((int)explode(":",$data['datasv'])[1]>65535)
            return array('code'=>3,'errotext'=>'数据服务器端口非法');


        $cfgsv=$data['cfgsv'];
        $datasv=$data['datasv'];
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setdnsport','cfgsv'=>$cfgsv,'datasv'=>$datasv],$token);
//        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setdnsport','cfgsv'=>'demo.qhs.cc:9803','datasv'=>'demo.qhs.cc:9802'],$token);
    }

    /**
     * 获取域名和端口
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:09
     */
    public function getdnsport($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'getdnsport'],$token);
    }

    /**
     * 设置IP和端口
     * @param $token
     * @param array $data
     * @return bool
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/3 13:56
     */
    public function setipport($token,$data=[])
    {
        dump($data);
        if(!isset($data['cfgsv'])|| !isset($data['datasv'])) {
            return false;
        }


        $cfghost=explode(":",$data['cfgsv'])[0];
        $dthost=explode(":",$data['datasv'])[0];

        if(!preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $cfghost))
            return array('code'=>2,'errotext'=>'控制服务器IP非法');

        if(!preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $dthost))
            return array('code'=>2,'errotext'=>'数据服务器IP非法');

        if((int)explode(":",$data['cfgsv'])[1]>65535)
            return array('code'=>3,'errotext'=>'数据服务器端口非法');

        if((int)explode(":",$data['datasv'])[1]>65535)
            return array('code'=>3,'errotext'=>'数据服务器端口非法');


        $cfgsv=$data['cfgsv'];
        $datasv=$data['datasv'];
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setipport','cfgsv'=>$cfgsv,'datasv'=>$datasv],$token);
//        return  $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setipport','cfgsv'=>'103.251.36.122:9803','datasv'=>'103.251.36.122:9802'],$token)
    }

    /**
     * 获取IP和端口
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:11
     */
    public function getipport($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'getipport'],$token);
    }

    /**
     * 获取地址策略
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:14
     */
    public function getaddroptin($token,$data=[])
    {
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'getaddroptin'],$token);
    }

    /**
     *  设置地址策略
     * @param $token
     * @param array $data
     * @return bool
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/3 13:58
     */
    public function setaddroptin($token,$data=[])
    {
        if(!isset($data['cfg'])|| !isset($data['data'])) return false;
        $cfgv=$data['cfg'];
        $datav=$data['data'];
        if(!in_array((int)$data['cfg'],[1,2])) return false;
        if(!in_array((int)$data['data'],[1,2])) return false;

        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setaddroptin','cfg'=>$cfgv,'data'=>$datav],$token);
    }

    /**
     * 获取WIFI信道列表
     * @param $token
     * @param array $data
     * @return array|bool|string
     */
    public function getWifiChannel($token, $data = [])
    {
        // WIFI设备序号
        if (!isset($data['no']) || !preg_match('/^[012][0-9A-Fa-f]$/', $data['no'])) return false;

        $data['do'] = 'getWifiChannel';
        return $this->protocol->setCommand(['dt' => '01', 'sdt' => '0010'], $data, $token);
    }


    /**
     * 获取WIFI信道列表
     * @param $token
     * @param array $data
     * @return array|bool|string
     */
    public function setWifiChannel($token, $data = [])
    {
        // WIFI设备序号
        if (!isset($data['no']) || !preg_match('/^[012][0-9A-Fa-f]$/', $data['no'])) return false;
        // 信道列表
        if (!isset($data['channel'])) return false;

        $channel = explode(',', $data['channel']);

        $total = 0;
        foreach ($channel as $item) {
            $sub = explode('-', $item);

            if (count($sub) == 1) {
                $total += (1 << (trim($sub[0]) - 1));
            } elseif (count($sub) == 2) {
                $sub[0] = trim($sub[0]);
                $sub[1] = trim($sub[1]);
                for ($i = $sub[0]; $i <= $sub[1]; ++$i) {
                    $total += (1 << ($i - 1));
                }
            }
        }

        dump($total);

        // 没有设置正确的信道
        if (!$total) return false;

        $data['channel'] = $total;

        $data['do'] = 'setWifiChannel';
        return $this->protocol->setCommand(['dt' => '01', 'sdt' => '0010'], $data, $token);
    }

    /**
     * 获取WIFI SSID
     * @param $token
     * @param array $data
     * @return array|bool|string
     */
    public function getWifiSSID($token, $data = [])
    {
        // 设备编号
        if (!isset($data['no1']) || !preg_match('/^[012][0-9A-Fa-f]$/', $data['no1'])) return false;

        // SSID序号
        if (!isset($data['no2']) || !preg_match('/^[0-7]$/', $data['no2'])) return false;

        $data['no2'] = '0' . $data['no2'];
        $data['do'] = 'getWifiSSID';
        return $this->protocol->setCommand(['dt' => '01', 'sdt' => '0010'], $data, $token);
    }

    /**
     * 设置WIFI SSID
     * @param $token
     * @param array $data
     * @return array|bool|string
     */
    public function setWifiSSID($token, $data = [])
    {
        // 设备编号
        if (!isset($data['no1']) || !preg_match('/^[012][0-9A-Fa-f]$/', $data['no1'])) return false;

        // SSID序号
        if (!isset($data['no2']) || !preg_match('/^[0-7]$/', $data['no2'])) return false;

        $data['no2'] = '0' . $data['no2'];

        if (!isset($data['ssid'])) return false;

        $data['ssid'] = bin2hex($data['ssid']);

        if (strlen($data['ssid']) / 2 > 32) return false;

        $data['do'] = 'setWifiSSID';

        return $this->protocol->setCommand(['dt' => '01', 'sdt' => '0010'], $data, $token);
    }

    /**
     * 设置重启或复位
     * @param $token
     * @param array $data
     * @return bool
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/3 13:59
     */
    public function setreboot($token,$data=[])
    {
        if(!isset($data['type'])) return false;
        if(!in_array((int)$data['type'],[1,2])) return false;
        return $this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setreboot','data'=>$data['type']],$token);
    }

    /**
     * 断开连接
     * @param $token
     * @param array $data1正常2重连3重发秘钥4强制断开
     * @return bool
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/3 14:00
     */
    public function setclose($token,$data=[])
    {
        if(!isset($data['type'])) return false;
        if(!in_array((int)$data['type'],[1,2,3,4])) return false;
        return$this->protocol->setCommand(['dt'=>'00','sdt'=>'0111','td'=>'10'],['do'=>'setclose','data'=>$data['type']],$token);
}

    /**
     *设置下线重连时间
     * setdowntime
     * @param $cfgtime 配置服务器下线时间
     * @param $datatime 数据服务下线时间
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:18
     */
    public function setdowntime($token,$data=[])
    {
        if(!isset($data['cfg'])|| !isset($data['data'])) return false;
        $cfgtime=$data['cfg'];
        $datatime=$data['data'];

        return $this->protocol->setCommand(['dt'=>'00','sdt'=>'0111','td'=>'10'],['do'=>'setdowntime','cfg'=>$cfgtime,'data'=>$datatime],$token);
    }

    /**
     * 响应客户端请求断开--探霸可暂时不用
     * @param $data //1正常2收到3拒绝断开
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: 2018/5/2 10:24
     */
    public function setcloseresponse($token,$data=[])
    {
        if(!isset($data['type'])) return false;

        return  $this->protocol->setCommand(['dt'=>'00','sdt'=>'0111','td'=>'10'],['do'=>'setcloseresponse','data'=>$data['type']],$token);
    }




    /**
     * 请求升级
     * @param $updata
    $updata=array(
    'uptsv'=>'123.58.43.16:9504',
    'frimware'=>'tanba.bin',
    'size'=>$filesize,
    'hardver'=>45,
    'softver'=>78
    );
     * @param $token
     * @return mixed
     * @Created by: xiebaoxin
     * @DateTime: xbxtime
     */
    public function setupdate($token,$data)
    {
        if(!isset($this->upconfig['upgradeserver']['host']) || !$this->upconfig['uploader']) {
            return array('code'=>1,'errotext'=>'升级服务器端口或路径错误');
        }
        //先检查服务器端口是否可以使用

        $upsvhost=$this->upconfig['upgradeserver']['host'];
        $upsvip=$this->upconfig['upgradeserver']['port'];

        //dump($upsvhost, $upsvip);

        /*if(!$this->check_tcp_upgrade($upsvhost,$upsvip)) {
            dump('!!!!!!!');
            return array('code' => 9, 'errotext' => '升级服务器不在线');
        }*/

       // dump('?????');

        if(isset($data['id']) &&isset($data['id']) &&  isset($data['hardver']) && isset($data['softver'])){
            $filedbinfo=$this->db->get('uploadbase',['filename','baseinfo','name'],['Id'=>$data['id']]);

            /*dump('-------');
            dump($filedbinfo);
            dump('--------')*/;
            if($filedbinfo ){//&& trim($filedbinfo['name'])==trim($data['name'])
                $data['frimware']=$filedbinfo['filename'];
                $file=$this->upconfig['uploader'].$data['frimware'];
                dump('--------');
                dump($file);
                dump('--------');
                if (!file_exists($file) || !is_readable($file)){
                    return array('code'=>4,'errotext'=>'升级文件不存在或不可读！');
                }else{

                    $fileifup=json_decode($filedbinfo['baseinfo'],true);
                    if(in_array($data['hardver'],$fileifup['hardver'])){
                        $data['uptsv'] =$upsvhost.":".$upsvip;
                        $data['size'] = abs(filesize($file));
                        $data['file'] = $file;
                        $data['xsumcode'] = dechex(check_sum($file));


                        echo "\n".$file."".$data['xsumcode']."\n";
//                        return array('code'=>99,'errotext'=>'升级文件请求成功！','data'=>$data);
                        return $data['size']>0?$this->protocol->setCommand(['dt'=>'01','sdt'=>'0010'],['do'=>'setupdate','data'=>$data],$token):false;
                    }
                    else{
                        return array('code'=>4,'errotext'=>'硬件版本不匹配！');
                    }

                }
            }else
                return array('code'=>3,'errotext'=>'升级文件无效或非法操作');

        }else
            return array('code'=>2,'errotext'=>'升级请求参数不能为空');

        return $retdata;

    }

    private function check_tcp_upgrade($host, $port)
    {
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        $ret=socket_connect($socket, $host, $port);
        socket_close($socket);

        return $ret;
    }

}